﻿Imports System.Drawing
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Text
Imports System.Windows.Forms
Imports Microsoft.Office.Core
Imports Microsoft.Vbe.Interop

Module Varaint
#Region "变量、常量"
    '//全局布尔
    Public ESC_TN As Boolean = False '控制其他按键的触发次数

    Public KeyTip_TN As Boolean = IIf(IO.File.Exists(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) & "\配置.ini") = True, Val(ReadOneString("配置信息", "是否智能缩进", Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) & "\配置.ini")), 1) '控制智能提示开关

    Public f As New CodeList '存储代码窗口
    Public ActiveCodePane_Handle As Integer
    Public ActiveHandle As Integer '存储代码编辑窗口
    '//存储所有的全局变量
    Public poBtnEvents As New Collection
    Public _VBE As VBE 'VBE对象
    Public _AddIn As AddIn
    Public _myToolbar As CommandBar
    Public CodeArr As Object '存储代码库数组
    Public DCodeArr As Dictionary(Of String, String) = New Dictionary(Of String, String) '把代码库写入字典，方便后面插入数据
    '//
    Public APPpath As String = System.Reflection.Assembly.GetExecutingAssembly().Location
    Public CodePath As String = ReadOneString("配置信息", "代码库路径", Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) & "\配置.ini")
    Public KeyWordPath As String = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) & "\Data\CodeList.xlsx"
    '/定义带事件的菜单按钮，否则点击无效
    Public ToolbatMenu As CommandBarPopup
    Public ToolbatMenu2 As CommandBarPopup

    Public ToolbatMenu3 As CommandBarPopup
    Public Btnarr() As CommandBarButton '存储按钮对象变量
    Public BtnCount As Int16 = 0 '存储按钮个数，计数器
    Public RightMenuBtn(3) As CommandBarButton '存储右键菜单按钮对象变量
    Public arr(,) As String '存储代码库
    Public _myToolBarButton1 As CommandBarButton
    Public _myToolBarButton2 As CommandBarButton
    Public _myToolBarButton3 As CommandBarButton
    '/
    Public CodeList_Handle As Integer = 0 '存储代码列表的句柄，初始设置为0
    '/常量

    Public Const WS_DISABLED = -2147483648

    Public Const SW_HIDE = 0
    Public Const SW_SHOWNOACTIVATE = 4
    Public Const SW_SHOW = 5
    Public Const WM_CLOSE = &H10
    Public Const GWL_STYLE = (-16)
    Public Const GWL_EXSTYLE = (-20)
    Public Const WS_BORDER = &H800000
    Public Const WS_CAPTION = &HC00000         '  WS_BORDER Or WS_DLGFRAME
    Public Const WS_CHILD = &H40000000
    Public Const WS_EX_TOOLWINDOW = &H80&
    Public Const WS_EX_TRANSPARENT As Long = &H20&
    Public Const WS_EX_LAYERED = &H80000
    Public Const LWA_ALPHA = &H2
    Public Const LWA_COLORKEY = &H1
    Public Const RGN_AND = 1
    Public Const RGN_OR = 2
    Public Const RGN_XOR = 3
    'hWndInsertAfter 参数可选值:
    Public Const HWND_TOP = 0 '在前面}
    Public Const HWND_BOTTOM = 1 '在后面}
    Public Const HWND_TOPMOST = -1 '在前面, 位于任何顶部窗口的前面}
    Public Const HWND_NOTOPMOST = -2 '在前面, 位于其他顶部窗口的后面}
    'uFlags 参数可选值:

    Public Const SWP_NOSIZE = &H1 '忽略 cxcy, 保持大小
    Public Const SWP_NOMOVE = &H2 '忽略 XY, 不改变位置
    Public Const SWP_NOZORDER = &H4 '忽略 hWndInsertAfter, 保持 Z 顺序
    Public Const SWP_NOREDRAW = &H8 '不重绘
    Public Const SWP_NOACTIVATE = &H10 '不激活
    Public Const SWP_FRAMECHANGED = &H20 '强制发送 WM_NCCALCSIZE 消息, 一般只是在改变大小时才发送此消息
    Public Const SWP_SHOWWINDOW = &H40 '显示窗口
    Public Const SWP_HIDEWINDOW = &H80 '隐藏窗口
    Public Const SWP_NOCOPYBITS = &H100 '丢弃客户区
    Public Const SWP_NOOWNERZORDER = &H200 '忽略 hWndInsertAfter, 不改变 Z 序列的所有者
    Public Const SWP_NOSENDCHANGING = &H400 '不发出 WM_WINDOWPOSCHANGING 消息
    Public Const SWP_DRAWFRAME = SWP_FRAMECHANGED '画边框
    Public Const SWP_NOREPOSITION = SWP_NOOWNERZORDER
    Public Const SWP_DEFERERASE = &H2000 '防止产生 WM_SYNCPAINT 消息
    Public Const SWP_ASYNCWINDOWPOS = &H4000 '若调用进程不拥有窗口, 系统会向拥有窗口的线程发出需求
    Public Const WM_SETFOCUS = &H7
    Public Const LOGPIXELSX = 88
    '//按键值
    Public Const PM_KEY_SPACE = 32 '空格键
    Public Const PM_KEY_BackSpace = 8 '删除键
    Public Const WM_KEYUP = &H101 '键弹起
    Public Const PM_KEY_Ctrl = &H11
    Public Const PM_KEY_Q = 192

    '//枚举、结构体
    '所选代码的起止行列信息定义数据类型
    Structure SelLineColInfo
        '//存储方法获取到的选择代码的位置信息，如果没有选择，则是光标的位置
        Public SLine As Long        '起始行
        Public SCol As Long        '起始列
        Public ELine As Long        '结束行
        Public ECol As Long        '结束列
    End Structure
    Structure RECT
        Dim Left As Integer
        Dim Top As Integer
        Dim Right As Integer
        Dim Bottom As Integer
    End Structure

    '函数功能：获得所选代码开始行列及结束行列信息
    Public Function VBGetSelection() As SelLineColInfo
        Dim SelInfo As SelLineColInfo  '数据类型
        _VBE.ActiveCodePane.GetSelection(SelInfo.SLine, SelInfo.SCol, SelInfo.ELine, SelInfo.ECol)
        '获取的行列信息输出
        VBGetSelection = SelInfo
    End Function

#End Region
#Region "各种API函数定义"
    Public Declare Function SetForegroundWindow Lib "user32" Alias "SetForegroundWindow" (ByVal hwnd As Integer) As Integer
    Public Declare Function SetWindowlong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Integer, ByVal nIndex As Integer, ByVal dwNewinteger As Integer) As Integer
    Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Integer) As Integer
    Public Declare Function SetFocus Lib "user32.dll" (ByVal hwnd As Integer) As Integer
    Public Declare Function IsWindow Lib "user32" (ByVal hwnd As Integer) As Boolean
    Public Declare Function GetCursorPos Lib "user32" (ByRef lpPoint As PointAPI) As Integer
    Public Declare Function ScreenToClient Lib "user32" (ByRef hwnd As Integer, ByRef lpPoint As Point) As Integer
    Public Declare Function ShowWindow Lib "user32" (ByVal hwnd As Integer, ByVal nCmdShow As Integer) As Integer
    Public Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Integer, ByVal hWndInsertAfter As Integer, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal wFlags As Integer) As Integer
    Public Declare Function IsWindowVisible Lib "user32" Alias "IsWindowVisible" (ByVal hwnd As Integer) As Integer
    ''Public Declare Function GetCaretPos Lib "user32" (lpPoint As PointAPI) As Integer
    Public Structure PointAPI '定义点坐标，存储光标位置
        Dim x As Integer
        Dim y As Integer
    End Structure
    '获取指定窗口（Form/控件）的位置及尺寸。该尺寸以相对于屏幕坐标左上角的屏幕坐标给出。
    Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Integer, ByRef lpRect As RECT) As Integer
    Public Declare Function GetClientRect Lib "user32" (ByVal hwnd As Integer, ByRef lpRect As RECT) As Integer


    <DllImport("user32")>
    Public Function GetCaretPos(ByRef lpPoint As PointAPI) As Integer
    End Function
    <DllImport("user32.dll")>
    Public Function GetForegroundWindow() As Integer
    End Function
    <DllImport("user32.dll")>
    Public Function AttachThreadInput(idAttach As Integer, idAttachTo As Integer, fAttach As Integer) As Integer
    End Function
    <DllImport("user32.dll")>
    Public Function GetWindowThreadProcessId(hWnd As Integer, ProcessId As Integer) As Integer
    End Function
    <DllImport("kernel32.dll")>
    Public Function GetCurrentThreadId() As Integer
    End Function
    '//获取光标所在窗口句柄
    Public Declare Function GetFocus Lib "user32" Alias "GetFocus" () As Integer
    Public Declare Function ClientToScreen Lib "user32" Alias "ClientToScreen" (ByVal hwnd As Integer, ByRef lpPoint As PointAPI) As Integer

    <System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="MoveWindow")>
    Public Function MoveWindow(ByVal hwnd As Integer, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal bRepaint As Integer) As Integer
    End Function
#End Region
#Region "读取Txt相关"




    Function ReadTextFile(ByVal FileName As String)
        '/读取txt文件，返回内容
        Dim TxtEncoderType As String = GetEncoder(FileName)
        Dim MyText As String
        Dim MyReader As StreamReader
        Select Case TxtEncoderType
            Case "UTF-8"
                MyReader = New StreamReader(FileName, Encoding.UTF8)
                MyText = MyReader.ReadToEnd()
                MyReader.Close()
            Case Else
                MyReader = New StreamReader(FileName, Encoding.Default)
                MyText = MyReader.ReadToEnd()
                MyReader.Close()
        End Select
        MyReader.Dispose()
        Return MyText
    End Function
    Function GetEncoder(filename) As String
        '//判断文本文件的编码格式
        Dim fs As FileStream = File.OpenRead(filename)
        Dim cdet As Ude.CharsetDetector = New Ude.CharsetDetector()
        cdet.Feed(fs)
        cdet.DataEnd()
        fs.Close()
        Return cdet.Charset
    End Function


    Function GetParent(Ctrl As Microsoft.Office.Core.CommandBarButton) As String
        '获取树形菜单的父级文字
        Dim s As String
        Try
            s = Ctrl.Parent.Parent.parent.parent.caption
        Catch
            Return ""
        End Try
        Return s
    End Function
#End Region
#Region "创建按钮相关自定义函数"

    '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    '创建按钮自定义函数
    '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    Function MakeANewButton(ByVal commandBar As CommandBar, ByVal caption As String, ByVal faceID As Integer, ByVal clickHandler As _CommandBarButtonEvents_ClickEventHandler) As CommandBarButton
        '//创建工具条新按钮自定义函数
        Try
            Dim newButton As CommandBarButton
            newButton = CType(commandBar.Controls.Add(MsoControlType.msoControlButton), CommandBarButton)
            newButton.Caption = caption
            newButton.FaceId = faceID
            AddHandler newButton.Click, clickHandler '绑定点击事件
            Return newButton
        Catch ex As System.Exception
            Return Nothing
        End Try
    End Function
    Function MakeANewMenuButton(ByVal ToolbatMenu As CommandBarPopup, ByVal caption As String, ByVal faceID As Integer, ByVal clickHandler As _CommandBarButtonEvents_ClickEventHandler) As CommandBarButton
        '//创建菜单区域新按钮自定义函数
        Try
            Dim newButton As CommandBarButton
            newButton = CType(ToolbatMenu.Controls.Add(MsoControlType.msoControlButton), CommandBarButton)
            newButton.Caption = caption
            newButton.FaceId = faceID
            AddHandler newButton.Click, clickHandler  '绑定点击事件
            Return newButton
        Catch ex As System.Exception
            Return Nothing
        End Try
    End Function
    Function MakeRightMenu(ByVal caption As String, ByVal faceID As Integer, ByVal clickHandler As _CommandBarButtonEvents_ClickEventHandler) As CommandBarButton
        '创建右键菜单区域的按钮
        Try
            Dim Btn As CommandBarButton
            Btn = _VBE.CommandBars("Code Window").Controls.Add(MsoControlType.msoControlButton,,, _VBE.CommandBars("Code Window").Controls.Count + 1, True)
            Btn.FaceId = faceID
            Btn.Caption = caption
            AddHandler Btn.Click, clickHandler  '绑定点击事件
            If caption = "删除空行" Then
                Btn.BeginGroup = True
            End If
            Return Btn
        Catch ex As Exception
            Return Nothing
        End Try
    End Function
    Function MakeRightMenu2(ByVal caption As String, ByVal faceID As Integer, ByVal clickHandler As _CommandBarButtonEvents_ClickEventHandler) As CommandBarButton
        '创建右键菜单区域的按钮
        Try
            Dim Btn As CommandBarButton
            Btn = ToolbatMenu3.Controls.Add(MsoControlType.msoControlButton,,, 1, True)
            Btn.FaceId = faceID
            Btn.Caption = caption
            AddHandler Btn.Click, clickHandler  '绑定点击事件
            Btn.BeginGroup = True
            Return Btn
        Catch ex As Exception
            Return Nothing
        End Try
    End Function

#End Region
End Module
